#pragma once

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Diagnostics;


namespace ARSys { namespace Connector {

#pragma unmanaged

//static std::map<int, ARControlStruct> gTokens;


#pragma managed

	/// <summary>
	/// Summary for ARTransaction
	/// </summary>
	public ref class ARTransaction :  public IDisposable
	{
	public:
		ARTransaction(int token)
			: token(token), proceeded(false), disposed(false)
		{
			ARControlStruct control = gTokens[token];
			ARStatusList status;

			try
			{
				int hr = ARBeginBulkEntryTransaction(&control, &status);
				if (hr >= AR_RETURN_ERROR) 
				{
					ARUtil::ThrowARException(L"ARBeginBulkEntryTransaction", hr, &status);
				}
			}
			finally
			{
				FreeARStatusList(&status, FALSE);
			}
		}

	protected:
		~ARTransaction()
		{
			// Dispose of managed resources.
			if(!proceeded)
			{
				try
				{
					Rollback();
				}
				catch(...)
				{
					// do nothing...
				}
				proceeded = true;
			}

			this->!ARTransaction();
			disposed = true;
		}
	protected:
		!ARTransaction()
		{
			// Dispose of unmanaged resources.
		}

	public:
		void Commit()
		{
			EndTransaction(AR_BULK_ENTRY_ACTION_SEND);
		}

	public:
		void Rollback()
		{
			EndTransaction(AR_BULK_ENTRY_ACTION_CANCEL);
		}

	private:
		void EndTransaction(unsigned int type)
		{
			try
			{
				ARControlStruct control = gTokens[token];
				ARStatusList status;
				ARBulkEntryReturnList bulkEntryReturnList;

				try
				{
					int hr = AREndBulkEntryTransaction(&control, type, &bulkEntryReturnList, &status);
					if (hr >= AR_RETURN_ERROR) 
					{
						ARUtil::ThrowARBulkException(L"AREndBulkEntryTransaction", hr, &status, &bulkEntryReturnList);
					}
				}
				finally
				{
					FreeARBulkEntryReturnList(&bulkEntryReturnList, FALSE);
					FreeARStatusList(&status, FALSE);
				}
			}
			finally
			{
				proceeded = true;
			}
		}

	private:
		bool disposed;
		bool proceeded;
		int token;


	};

}}
